﻿namespace KinonekoSoftware.CodariaDB.Core
{
    /// <summary>
    /// 维护 <see cref="Concept"/> 概念实体的数据引擎。
    /// </summary>
    /// <remarks>
    /// <para>前缀以_开头的都是框架内代码。</para>
    /// </remarks>
    public sealed class ConceptSystem : Engine
    {
        /// <summary>
        /// 添加 <see cref="Concept"/> 概念实体， 框架代码，请勿在代码中使用.
        /// </summary>
        /// <param name="msg">框架内消息。</param>
        public void Add(ConceptOP_MSG msg)
        {
            var concept = new Concept
            {
                Id       = msg.ConceptID,
                Name     = msg.ConceptName,
                EngineID = msg.ConceptEngineID,
                Avatar   = msg.ConceptAvatar,
                Intro    = msg.ConceptIntro,
            };
            InsideDB.Insert(concept);
            NotifySelfChanged(msg);
        }

        /// <summary>
        /// 修改 <see cref="Concept"/> 概念实体，框架代码，请勿在代码中使用.
        /// </summary>
        /// <param name="msg">框架内消息。</param>
        public void Update(ConceptOP_MSG msg)
        {
            var concept = InsideDB.FindById(msg.ConceptID);

            if (concept is null)
            {
                Add(new ConceptOP_MSG
                {
                    ConceptID       = msg.ConceptID,
                    ConceptName     = msg.ConceptName,
                    ConceptEngineID = msg.ConceptEngineID,
                    ConceptAvatar   = msg.ConceptAvatar,
                    ConceptIntro    = msg.ConceptIntro,
                    Action          = Database_Action.Added,
                });
                return;
            }

            msg.OldName    = concept.Name;
            concept.Avatar = msg.ConceptAvatar;
            concept.Intro  = msg.ConceptIntro;
            concept.Name   = msg.ConceptName;

            InsideDB.Upsert(concept);
            NotifySelfChanged(msg);
        }

        /// <summary>
        /// 移除 <see cref="Concept"/> 概念实体，框架代码，请勿在代码中使用.
        /// </summary>
        /// <param name="msg">框架内消息。</param>
        public void Remove(ConceptOP_MSG msg)
        {
            InsideDB.Delete(msg.ConceptID);
            NotifySelfChanged(msg);
        }

        /// <summary>
        /// 清空所有概念实体，框架代码，请勿在代码中使用.
        /// </summary>
        public void Clear()
        {
            InsideDB.DeleteAll();
            NotifySelfChanged(ConceptOP_MSG.Clear);
        }

        /// <summary>
        /// 接受消息，并根据消息调用指定的代码。框架代码，请勿在代码中使用.
        /// </summary>
        public void Accept(ConceptOP_MSG msg)
        {
            if (msg is null)
            {
                return;
            }

            if (msg.Action == Database_Action.Added)
            {
                Add(msg);
            }
            else if (msg.Action == Database_Action.Modified)
            {
                Update(msg);
            }
            else
            {
                Remove(msg);
            }
        }


        private void NotifySelfChanged(ConceptOP_MSG msg)
        {
            Modified();

            EntityChangedHandler?.Invoke(msg);
        }
        
        
        public IEnumerable<Concept> Get() => InsideDB.FindAll();
        public Concept Get(string id) => InsideDB.FindById(id);

        protected override void OnDatabaseOpening(RepositoryOpenContext context)
        {
            InsideDB = context.Repository.Get<Concept>(CollectionNames.ConceptDB);
        }

        protected override void OnDatabaseClosing(ILogger logger)
        {
            InsideDB = null;
        }

        public override string EngineID => EngineNames.Concept;

        public ILiteCollection<Concept> InsideDB { get; private set; }
        
        /// <summary>
        /// 
        /// </summary>
        public Action<ConceptOP_MSG> EntityChangedHandler { get; set; }
    }
}